/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package fi.uba.algo3.tp3;

import ar.uba.fi.algo3.titiritero.ControladorJuego;
import ar.uba.fi.algo3.titiritero.vista.Circulo;
import fi.uba.algo3.tp3.controller.UserController;
import fi.uba.algo3.tp3.loader.PersonajeImagesLoader;
import fi.uba.algo3.tp3.modelo.actores.FantasmaBobo;
import fi.uba.algo3.tp3.modelo.actores.FantasmaCamaleon;
import fi.uba.algo3.tp3.modelo.actores.FantasmaListo;
import fi.uba.algo3.tp3.modelo.actores.FantasmaRapido;
import fi.uba.algo3.tp3.modelo.actores.Pacman;
import fi.uba.algo3.tp3.modelo.actores.exceptions.PosicionInvalidaException;
import fi.uba.algo3.tp3.modelo.animados.PuntoBonusTimer;
import fi.uba.algo3.tp3.modelo.animados.PuntoTimer;
import fi.uba.algo3.tp3.modelo.contenedor.LaberintoContenedor;
import fi.uba.algo3.tp3.modelo.contenedor.config.LaberintoConfigurationLoader;
import fi.uba.algo3.tp3.modelo.inanimados.Comible;
import fi.uba.algo3.tp3.modelo.inanimados.Obstaculo;
import fi.uba.algo3.tp3.modelo.inanimados.ObstaculoFijo;
import fi.uba.algo3.tp3.modelo.inanimados.ObstaculoPared;
import fi.uba.algo3.tp3.modelo.inanimados.Punto;
import fi.uba.algo3.tp3.modelo.inanimados.PuntoBonus;
import fi.uba.algo3.tp3.modelo.inanimados.PuntoPoder;
import fi.uba.algo3.tp3.modelo.inanimados.PuntosJugador;
import fi.uba.algo3.tp3.modelo.inanimados.VidasJugador;
import fi.uba.algo3.tp3.modelo.notificaciones.StateNotification;
import fi.uba.algo3.tp3.modelo.servicios.ServicioJuego;
import fi.uba.algo3.tp3.utils.dijkstra.DijkstraGraph;
import fi.uba.algo3.tp3.utils.dijkstra.builder.GraphLoader;
import fi.uba.algo3.tp3.vista.actores.VistaJugador;
import fi.uba.algo3.tp3.vista.contenedor.VistaJaula;
import fi.uba.algo3.tp3.vista.contenedor.VistaLaberinto;
import fi.uba.algo3.tp3.vista.inanimados.VistaComible;
import fi.uba.algo3.tp3.vista.inanimados.VistaComibleBonus;
import fi.uba.algo3.tp3.vista.inanimados.VistaObstaculo;
import fi.uba.algo3.tp3.vista.inanimados.VistaTexto;
import fi.uba.algo3.tp3.vista.inanimados.VistaVidas;
import fi.uba.algo3.tp3.vista.ventana.VentanaPrincipal;
import java.awt.Color;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.me.JSONException;

/**
 *
 * @author arrodriguez
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            /*
             * Primero instancio mi modelo
             */
            //Pos de la jaula
            LaberintoContenedor contenedor = null;

            LaberintoConfigurationLoader loader = null;

            PuntoBonusTimer bonusTimer = null;

            try {
                
                loader = new LaberintoConfigurationLoader("src/fi/uba/algo3/tp3/modelo/contenedor/config/laberinto.json");

                contenedor = loader.loadConfiguration();

            } catch (JSONException ex) {

                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);

            } catch (FileNotFoundException ex) {

                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);

            } catch (IOException ex) {

                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);

            }

            int bloqueAncho = loader.getBloqueAncho();

            int bloqueAlto = loader.getBloqueAlto();

            ServicioJuego servicio = new ServicioJuego(contenedor);

            PuntoTimer timer = new PuntoTimer(servicio);
            
            servicio.setPuntoTimer(timer);
            // El ancho de la imagen es 20 la colision hago 20/2
            Pacman pacman = new Pacman(servicio, 10);
            
            
            FantasmaBobo bobo = new FantasmaBobo(servicio,10);

            FantasmaCamaleon camaleon = new FantasmaCamaleon(servicio,10);

            String filePath = "src/fi/uba/algo3/tp3/utils/dijkstra/builder/graph.json";

            GraphLoader graphLoader = new GraphLoader(filePath);

            DijkstraGraph graph = graphLoader.loadGraphFromJSONFile();

            //
            FantasmaListo listo = new FantasmaListo(servicio,10);
            
            //listo.setGraph(graph);
            
            FantasmaRapido rapido = new FantasmaRapido(servicio,10);


            try {
                // TODO cambiar cuando seteamos el punto bonus
                pacman.setX(5*bloqueAncho);

                pacman.setY(6*bloqueAlto);

                pacman.setPosicionInicialX(5*bloqueAncho);

                pacman.setPosicionInicialY(6*bloqueAlto);

                bobo.setX(5*bloqueAncho+7);

                bobo.setY(4*bloqueAlto+7);

                bobo.setPosicionInicialX(5*bloqueAncho+7);

                bobo.setPosicionInicialY(4*bloqueAlto+7);

                rapido.setX(6*bloqueAncho+7);

                rapido.setY(4*bloqueAlto+7);

                rapido.setPosicionInicialX(6*bloqueAncho+7);

                rapido.setPosicionInicialY(4*bloqueAlto+7);

                camaleon.setX(4*bloqueAncho+7);

                camaleon.setY(4*bloqueAlto+7);

                camaleon.setPosicionInicialX(4*bloqueAncho+7);

                camaleon.setPosicionInicialY(4*bloqueAlto+7);
                
                listo.setX(4*bloqueAncho+7);
                
                listo.setY(5*bloqueAlto+7);
                
                listo.setPosicionInicialX(4*bloqueAncho+7);
                
                listo.setPosicionInicialY(5*bloqueAlto+7);

            } catch (PosicionInvalidaException ex) {

                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                

            }
            servicio.setPacman(pacman);

            servicio.agregarFantasmas(rapido);

            servicio.agregarFantasmas(camaleon);

            servicio.agregarFantasmas(bobo);
            
            servicio.agregarFantasmas(listo);

            // Vista
            VistaLaberinto laberinto = new VistaLaberinto(contenedor.getAncho(), contenedor.getAlto()+50);

            laberinto.setPosicionable(contenedor);

            ObstaculoFijo bean = contenedor.obtenerJaula();

            VistaJaula jaula = new VistaJaula(bean.getAncho(), bean.getAlto());

            jaula.setPosicionable(bean);

            laberinto.agregarJaula(jaula);

            for (Obstaculo pared : contenedor.getObstaculos()) {
                ObstaculoPared paredObs = (ObstaculoPared) pared;
                VistaObstaculo obstaculo = new VistaObstaculo(paredObs.getAncho(), paredObs.getAlto());
                obstaculo.setPosicionable(pared);
                laberinto.agregarCuadrado(obstaculo);
            }

            for (Comible punto : contenedor.getComibles()) {
                Circulo circulo = null;
                Punto puntoExt = (Punto) punto;
                if (punto instanceof PuntoBonus) {
                    circulo = new VistaComibleBonus(10);
                    puntoExt.setObservador((VistaComible) circulo);
                    bonusTimer = new PuntoBonusTimer(servicio, (PuntoBonus) punto);
                    circulo.setPosicionable(punto);
                    servicio.setTimerBonus(bonusTimer);
                    puntoExt.setRadio(10);
                } else if (punto instanceof PuntoPoder) {
                    circulo = new VistaComible(10);
                    circulo.setPosicionable(punto);
                    puntoExt.setObservador((VistaComible) circulo);
                    puntoExt.setRadio(10);
                } else {
                    circulo = new VistaComible(5);
                    circulo.setPosicionable(punto);
                    puntoExt.setObservador((VistaComible) circulo);
                    puntoExt.setRadio(5);
                }
                puntoExt.setServicio(servicio);
                laberinto.agregarCirculo(circulo);
            }

            VistaTexto textoPuntos = new VistaTexto(50, 20);

            PuntosJugador puntos = new PuntosJugador(150, 11*bloqueAlto);

            textoPuntos.setPosicionable(puntos);
                   
            VistaVidas vidas=new VistaVidas(50, 20);
            for(int i=0;i<3;i++){
                VidasJugador jugador = new VidasJugador(20+(i*12),11*bloqueAlto);
                Circulo circulo = new Circulo(10);
                circulo.setColor(Color.yellow);
                circulo.setPosicionable(jugador);
                vidas.agrearVida(circulo);
            }
            
            VistaJugador jugador = new VistaJugador(StateNotification.IZQUIERDA);

            VistaJugador fantasmaBobo = new VistaJugador(StateNotification.NORMAL);

            VistaJugador fantasmaRapido = new VistaJugador(StateNotification.NORMAL);

            VistaJugador fantasmaListo = new VistaJugador(StateNotification.NORMAL);
            
            VistaJugador fantasmaCamaleon = new VistaJugador(StateNotification.NORMAL);

            PersonajeImagesLoader pacmanLoader = new PersonajeImagesLoader(pacman);

            PersonajeImagesLoader pacmanLoaderBobo = new PersonajeImagesLoader(bobo);

            PersonajeImagesLoader pacmanLoaderCamaleon = new PersonajeImagesLoader(camaleon);

            PersonajeImagesLoader pacmanLoaderListo = new PersonajeImagesLoader(listo);

            PersonajeImagesLoader pacmanLoaderRapido = new PersonajeImagesLoader(rapido);

            pacmanLoader.cargarAnimaciones("src/fi/uba/algo3/tp3/vista/actores/imagen/graphics/animacionPacman.cfg", jugador);
            //Rosa : Listo
            //Verde : Camaleon
            //Naranja : Bobo
            //Celeste : Rapido
            pacmanLoaderListo.cargarAnimaciones("src/fi/uba/algo3/tp3/vista/actores/imagen/graphics/animacionesFantasma1.cfg", fantasmaListo);

            pacmanLoaderCamaleon.cargarAnimaciones("src/fi/uba/algo3/tp3/vista/actores/imagen/graphics/animacionesFantasma2.cfg", fantasmaCamaleon);

            pacmanLoaderBobo.cargarAnimaciones("src/fi/uba/algo3/tp3/vista/actores/imagen/graphics/animacionesFantasma3.cfg", fantasmaBobo);
            
            pacmanLoaderRapido.cargarAnimaciones("src/fi/uba/algo3/tp3/vista/actores/imagen/graphics/animacionesFantasma4.cfg", fantasmaRapido);

            /*
             * Luego instancio los objetos del framework: una ventana y el controlador
             */

            ControladorJuego controlador = new ControladorJuego();

            UserController controladorUsuario = new UserController(servicio);

            VentanaPrincipal ventana = new VentanaPrincipal(controlador, controladorUsuario);

            controlador.setSuperficieDeDibujo(ventana.getSuperficieDeDibujo());

            ventana.setVisible(true);

            controlador.agregarObjetoVivo(pacman);

            controlador.agregarObjetoVivo(bobo);

            controlador.agregarObjetoVivo(camaleon);

            controlador.agregarObjetoVivo(listo);

            controlador.agregarObjetoVivo(rapido);

            controlador.agregarObjetoVivo(timer);

            controlador.agregarObjetoVivo(bonusTimer);
            
            controlador.agregarDibujable(laberinto);

            controlador.agregarDibujable(vidas);

            controlador.agregarDibujable(textoPuntos);

            controlador.agregarDibujable(jugador);

            controlador.agregarDibujable(fantasmaBobo);

            controlador.agregarDibujable(fantasmaCamaleon);
            
            controlador.agregarDibujable(fantasmaListo);

            controlador.agregarDibujable(fantasmaRapido);

            servicio.agregarObservador(fantasmaBobo);

            servicio.agregarObservador(fantasmaRapido);

            servicio.agregarObservador(fantasmaCamaleon);

            servicio.agregarObservador(fantasmaListo);

            servicio.setControlador(controlador);

            servicio.iniciarServicioJuego();

            servicio.setVidasObserver(vidas);

            controlador.setIntervaloSimulacion(15);

            controlador.comenzarJuego();

        } catch (FileNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
